home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Dev / debug / SegTracker.lha / SegTracker / SegTracker.doc < prev    next >
Text File  |  2004-08-09  |  10KB  |  295 lines

  1. SegTracker                                                        SegTracker
  2.  
  3.    NAME
  4.     SegTracker - A global SegList tracking utility
  5.  
  6.    SYNOPSIS
  7.     A global tracking utility for disk loaded files including
  8.     libraries and devices.  If placed in the startup-sequence
  9.     right after SetPatch, it will track all disk loaded segments
  10.     (other than those loaded by SetPatch).
  11.  
  12.    FUNCTION
  13.     SegTracker will patch dos.library's LoadSeg(), NewLoadSeg() and
  14.     UnLoadSeg() functions in order to track the SegLists that are
  15.     loaded. SegTracker keeps those SegLists stored in a "safe" manner
  16.     and even handles programs which split their SegList.
  17.  
  18.     The first time the program is run, it installs the patches
  19.     and semaphore.  After that point, it just finds the semaphore
  20.     and uses it.
  21.  
  22.     When SegTracker is installed, it will scan the Kickstart ROM for
  23.     ROM modules and the KickMemList for ROM updates (OS 3.5/3.9) and
  24.     add their location/size to the tracking list such that addresses
  25.     within those modules can be identified.  Note that the offsets
  26.     of ROM modules are based on the location of the module's RomTag
  27.     whereas ROM updates get tracked with their KickMemList entries.
  28.     The NOROM option will prevent this feature from being installed.
  29.  
  30.     Additionally, KickMemList will be scanned for 3rd-party KickTags.
  31.     You can prevent this behaviour with the NOKICKTAG option.
  32.  
  33.     By using SegTracker, it will be possible to better identify
  34.     where Enforcer hits come from when dealing with libraries
  35.     and devices.  Basically, it is a system-global Hunk-o-matic.
  36.  
  37.     External programs can then pass in an address to SegTracker
  38.     either via the command line or via the given function pointer
  39.     in the SegTracker semaphore and get back results as to what
  40.     hunk and offset the address is at.
  41.  
  42.     To work with the function directly, you need to find the
  43.     semaphore of "SegTracker" using FindSemaphore().
  44.     The structure found will be the following:
  45.  
  46.     struct  SegSem
  47.     {
  48.     struct  SignalSemaphore seg_Semaphore;
  49.             SegTrack        *seg_Find;
  50.     };
  51.  
  52.     The function pointer points to a routine that takes an address
  53.     and two pointers to longwords for returning the Segment number
  54.     and Offset within the segment.  The function returns the name
  55.     of the file loaded.  Note that you must call this function
  56.     while in Forbid() and then copy the name as the seglist may
  57.     be UnLoadSeg'ed at any moment and the name string will then
  58.     no longer be in memory.
  59.  
  60.     typedef    char (* __asm SegTrack(register __a0 ULONG Address,
  61.                                    register __a1 ULONG *SegNum,
  62.                                    register __a2 ULONG *Offset));
  63.  
  64.     The above is for use in C code function pointer prototype
  65.     in SAS/C 5 and 6.
  66.  
  67.    INPUTS
  68.     FIND/M      - Find the hex (in $xxxxx format) address in the
  69.                   tracked segments. Multiple addresses can be given.
  70.  
  71.     SHOW/S      - Shows all of the segments being tracked.
  72.  
  73.     DUMP/S      - Displays all of the segment elements being tracked.
  74.  
  75.     NOROM/S     - Tells SegTracker not to scan ROM/KickMemList when
  76.                   it is installed, thus not adding ROM addresses to
  77.                   the tracking list.
  78.  
  79.     NOKICKTAG/S - Tells SegTracker not to scan KickMemList for other
  80.                   KickTags when it is installed, thus not adding
  81.                   any KickTag addresses to the tracking list.
  82.  
  83.     FULLPATH/S  - Usually, the [New]LoadSeg() patch tracks filenames
  84.                   as they are given to the respective function. With
  85.                   this option, it will track the full path.
  86.  
  87.     NOPATH/S    - Usually, the [New]LoadSeg() patch tracks filenames
  88.                   as they are given to the respective function. With
  89.                   this option, it will strip path information.
  90.                   Additionally, NOPATH determines the output format
  91.                   of the SHOW, DUMP and FIND functions.
  92.  
  93.     Options are not available from Workbench as they require the CLI.
  94.     However, you can run SegTracker from Workbench to install it.
  95.  
  96.    EXAMPLE USAGE
  97.     /*
  98.      * A simple program that will "find" given addresses in the SegLists
  99.      * This program has been compiled with SAS/C 6.2 without errors or
  100.      * warnings.
  101.      *
  102.      * Compiler options:
  103.      * DATA=FARONLY PARAMETERS=REGISTER NOSTACKCHECK
  104.      * NOMULTIPLEINCLUDES STRINGMERGE STRUCTUREEQUIVALENCE
  105.      * MULTIPLECHARACTERCONSTANTS DEBUG=LINE NOVERSION
  106.      * OPTIMIZE OPTIMIZERINLOCAL NOICONS
  107.      *
  108.      * Linker options:
  109.      * FindSeg.o TO FindSeg SMALLCODE SMALLDATA NODEBUG LIB LIB:sc.lib
  110.      */
  111.     #include <exec/types.h>
  112.     #include <exec/execbase.h>
  113.     #include <exec/libraries.h>
  114.     #include <exec/semaphores.h>
  115.     #include <dos/dos.h>
  116.     #include <dos/dosextens.h>
  117.     #include <dos/rdargs.h>
  118.  
  119.     #include <clib/exec_protos.h>
  120.     #include <pragmas/exec_sysbase_pragmas.h>
  121.  
  122.     #include <clib/dos_protos.h>
  123.     #include <pragmas/dos_pragmas.h>
  124.  
  125.     #include <string.h>
  126.  
  127.     #include "FindSeg_rev.h"
  128.  
  129.     #define EXECBASE (*(struct ExecBase **)4)
  130.  
  131.     typedef char (* __asm SegTrack(register __a0 ULONG,
  132.                                    register __a1 ULONG *,
  133.                                    register __a2 ULONG *));
  134.  
  135.     struct SegSem
  136.     {
  137.     struct SignalSemaphore seg_Semaphore;
  138.            SegTrack        *seg_Find;
  139.     };
  140.  
  141.     #define SEG_SEM "SegTracker"
  142.  
  143.     #define TEMPLATE "FIND/M" VERSTAG
  144.  
  145.     #define OPT_FIND  0
  146.     #define OPT_COUNT 1
  147.  
  148.     ULONG cmd(void)
  149.     {
  150.     struct ExecBase *SysBase;
  151.     struct Library  *DOSBase;
  152.     struct RDArgs   *rdargs;
  153.            ULONG    rc=RETURN_FAIL;
  154.     struct SegSem   *segSem;
  155.            char     **hex;
  156.            LONG     opts[OPT_COUNT];
  157.  
  158.       SysBase = EXECBASE;
  159.       if (DOSBase = OpenLibrary("dos.library",37))
  160.       {
  161.         memset((char *)opts, 0, sizeof(opts));
  162.  
  163.         if (!(rdargs = ReadArgs(TEMPLATE, opts, NULL)))
  164.         {
  165.           PrintFault(IoErr(),NULL);
  166.         }
  167.         else if (CheckSignal(SIGBREAKF_CTRL_C))
  168.         {
  169.           PrintFault(ERROR_BREAK,NULL);
  170.         }
  171.         else if (segSem=(struct SegSem *)FindSemaphore(SEG_SEM))
  172.         {
  173.           rc=RETURN_OK;
  174.           if (opts[OPT_FIND])
  175.           {
  176.             for (hex=(char **)opts[OPT_FIND];(*hex);hex++)
  177.             {
  178.             char  *p;
  179.             ULONG val;
  180.             ULONG tmp[4];
  181.             ULONG c;
  182.  
  183.               val=0;
  184.               p=*hex;
  185.               if (*p=='$') p++; /* Support $hex */
  186.               while (*p)
  187.               {
  188.                 c=(ULONG)*p;
  189.                 if ((c>='a') && (c<='f')) c-=32;
  190.                 c-='0';
  191.                 if (c>9)
  192.                 {
  193.                   c-=7;
  194.                   if (c<10) c=16;
  195.                 }
  196.  
  197.                 if (c<16)
  198.                 {
  199.                   val=(val << 4) + c;
  200.                   p++;
  201.                 }
  202.                 else
  203.                 {
  204.                   val=0;
  205.                   p=&p[strlen(p)];
  206.                 }
  207.               }
  208.  
  209.               /*
  210.                * Ok, we need to do this within Forbid()
  211.                * as segments can unload at ANY time, including
  212.                * during AllocMem(), so we use a stack buffer...
  213.                *
  214.                */
  215.               Forbid();
  216.               if (p=(*segSem->seg_Find)(tmp[0]=val,&tmp[2],&tmp[3]))
  217.               {
  218.               char Buffer[200];
  219.  
  220.                 stccpy(Buffer,p,200);
  221.                 tmp[1]=(ULONG)Buffer;
  222.                 VPrintf("$%08lx - %s : Hunk %ld, Offset $%08lx",tmp);
  223.  
  224.                 /*
  225.                  * Now get the SegList address by passing the
  226.                  * same pointer for both hunk & offset.  Note
  227.                  * that this is only in the newer SegTrackers
  228.                  * and will not work with ROM/KickTag entries.
  229.                  * To test if this worked, check if the result
  230.                  * of this call is either a hunk or an offset.
  231.                  */
  232.                 (*segSem->seg_Find)(val,&tmp[0],&tmp[0]);
  233.                 /*
  234.                  * This "kludge" is for compatibility reasons
  235.                  * Check if result is the same as either the hunk
  236.                  * or the offset.  If so, do not print it...
  237.                  */
  238.                 if ((tmp[0]!=tmp[2]) && (tmp[0]!=tmp[3]))
  239.                 {
  240.                   VPrintf(", SegList $%08lx",tmp);
  241.                 }
  242.  
  243.                 PutStr("\n");
  244.               }
  245.               else VPrintf("$%08lx - Not found\n",tmp);
  246.               Permit();
  247.             }
  248.           }
  249.         }
  250.         else PutStr("Could not find SegTracker semaphore.\n");
  251.  
  252.         if (rdargs) FreeArgs(rdargs);
  253.         CloseLibrary(DOSBase);
  254.       }
  255.       else if (DOSBase=OpenLibrary("dos.library",0))
  256.       {
  257.         Write(Output(),"Requires Kickstart 2.04 (37.175) or later.\n",43);
  258.         CloseLibrary(DOSBase);
  259.       }
  260.  
  261.       return(rc);
  262.     }
  263.  
  264.    NOTES
  265.     The earlier this command is run, the better off it will be in
  266.     tracking disk loaded segments.  Under debug usage, you may
  267.     wish to run the command right *AFTER* SetPatch.
  268.  
  269.     Some things may not call UnLoadSeg() to free their seglists.
  270.     There is no way SegTracker can follow a seglist that is not
  271.     unloaded via the dos.library call to UnLoadSeg().  For this
  272.     reason, SegTracker adds new LoadSeg() segments to the top
  273.     of its list.  This way, if any old segments are still on
  274.     the list but have been unloaded via some other method they
  275.     will not clash with newer segments during the find operation.
  276.  
  277.     Note that the resident list is one such place where UnLoadSeg()
  278.     is not called to free the seglist.  Thus, if something is made
  279.     resident and then later unloaded it will still be listed as
  280.     tracked by SegTracker.
  281.  
  282.     In order to support a new feature in CPR, the SegTracker function
  283.     got a "kludge" added to it.  If a segment is found, you can then
  284.     call the function again with the same address but with having
  285.     both pointers point to the same longword of storage.  By doing
  286.     this, the function will now return (in that longword) the
  287.     SegList pointer (CPTR not BPTR) of the file that contains
  288.     the address.  The reason this method was used was so it
  289.     would be compatible with older SegTracker versions.  In older
  290.     versions you would not get the result you wanted but you would
  291.     also not crash.  See the example above for more details on how
  292.     to use this feature.  The SegTracker FIND option has been
  293.     expanded to include this information.
  294.  
  295.